import math
import random
from pyglet.gl import *
import data
import window
import trawler
from vec2d import Vec2d

class Background:
    """Game background graphics"""

    SKY_TOP_COLOR = (0.9, 0.95, 1.0)
    SKY_BOTTOM_COLOR = (0.5, 0.7, 0.95)
    
    WAVE_SPEED = 0.75
    WAVE_OCC = 0.07
    WAVE_FREQ = 3.0
    WATER_TOP = 0.7    
    WATER_TOP_COLOR = (0.2, 0.5, 0.8)
    WATER_BOTTOM_COLOR = (0.025, 0.035, 0.05)
    FRONT_WAVE_COLOR = WATER_TOP_COLOR
    BACK_WAVE_COLOR = (0.1, 0.25, 0.4)
    WAVES = 10.0
    WAVE_HEIGHT = 0.025
    WAVE_TOP = WATER_TOP + WAVE_HEIGHT
    WAVE_BOTTOM = WATER_TOP
    BACK_WAVE_OFFSET = 0.03
    CLOUD_SPEED_DEVIATION = 5
    CLOUD_OPACITY = 0.7
    NUM_CLOUDS = 3
    CLOUD_SIZE_DEVIATION = 0.2


    def __init__(self, game):
        self.wave_tex = data.texture('wave.png')
        self.wave_pos = 0
        self.time = 0
        self.boat_sprite = pyglet.sprite.Sprite(data.image('dinghy.png'))
        self.man_back_sprite = pyglet.sprite.Sprite(data.image('fisherman-back.png'))
        self.man_front_sprite = pyglet.sprite.Sprite(data.image('fisherman-front.png'))
        self.sky_batch = pyglet.graphics.Batch()
        self.sun_sprite = pyglet.sprite.Sprite(data.image('sun.png'),
            x=500, y=350, batch=self.sky_batch)
        self.clouds = []
        cloud_scale = max(random.gauss(0.5, self.CLOUD_SIZE_DEVIATION), 0.2)
        for i in range(self.NUM_CLOUDS):
            cloud = pyglet.sprite.Sprite(data.image('cloud.png'), batch=self.sky_batch)
            cloud.y = random.randint(480, 560)
            cloud.x = random.randint(0,game.width)
            cloud.opacity = 255 * self.CLOUD_OPACITY
            cloud.scale = cloud_scale
            cloud_scale += random.random() * 0.75
            cloud.speed = random.gauss(0.0, self.CLOUD_SPEED_DEVIATION)
            self.clouds.append(cloud)
        self.max_right = game.width
        self.trawler = trawler.Trawler(game)
    
    def update(self, dt):
        self.time += dt
        self.wave_pos = (self.time * self.WAVE_SPEED 
            + math.sin(self.time * self.WAVE_FREQ) * self.WAVE_OCC)
        self.back_wave_top = self.WAVE_TOP + math.sin(self.time * self.WAVE_FREQ) * 0.01
        self.front_wave_top = self.WAVE_TOP + math.cos(self.time * self.WAVE_FREQ) * 0.01
        self.boat_sprite.rotation = math.sin(self.time * self.WAVE_FREQ / 3.0) * 3.0 - 1.0
        self.boat_sprite.y -= math.sin(self.time * self.WAVE_FREQ) * 0.08
        boat_orient = Vec2d(0, self.boat_sprite.width / 2)
        boat_orient.rotate(self.boat_sprite.rotation + 90)
        self.man_front_sprite.y = self.man_height + boat_orient.y + (
            self.boat_sprite.y - self.boat_height)
        self.man_back_sprite.y = self.man_front_sprite.y
        for cloud in self.clouds:
            cloud.x += cloud.speed * dt
            if cloud.x < -cloud.width:
                cloud.x = self.max_right
            elif cloud.x > self.max_right:
                cloud.x = -cloud.width
        self.trawler.update(dt)

    def resize(self, game):
        self.boat_sprite.set_position(0.01 * game.width, self.WAVE_BOTTOM * game.height * 0.935)
        self.boat_sprite.scale = 0.65
        self.boat_height = self.WAVE_BOTTOM * game.height * 0.935
        self.man_height = self.WAVE_BOTTOM * game.height * 0.98
        self.man_back_sprite.set_position(self.boat_sprite.x + self.boat_sprite.width * 0.63,
            self.man_height)
        self.man_back_sprite.scale = 0.65
        self.man_front_sprite.set_position(self.boat_sprite.x + self.boat_sprite.width * 0.63,
            self.man_height)
        self.man_front_sprite.scale = 0.65
    
    def draw(self, game):
        glDisable(self.wave_tex.target)
        glBegin(GL_QUADS)
        # Sky
        glColor3f(*self.SKY_BOTTOM_COLOR)
        glVertex2f(0, self.WATER_TOP * game.height)
        glVertex2f(game.width, self.WATER_TOP * game.height)
        glColor3f(*self.SKY_TOP_COLOR)
        glVertex2f(game.width, game.height)
        glVertex2f(0, game.height)
        glEnd()

        self.sky_batch.draw()
        self.trawler.draw_distant()

        # Waves
        glEnable(self.wave_tex.target)
        glBindTexture(self.wave_tex.target, self.wave_tex.id)
        glTexParameteri(self.wave_tex.target, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(self.wave_tex.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)

        glBegin(GL_QUADS)
        glColor3f(*self.BACK_WAVE_COLOR)
        glTexCoord2f(-self.wave_pos, -self.BACK_WAVE_OFFSET*40)
        glVertex2f(0, self.WAVE_BOTTOM * game.height)
        glTexCoord2f(self.WAVES - self.wave_pos, -self.BACK_WAVE_OFFSET*40)
        glVertex2f(game.width, self.WAVE_BOTTOM * game.height)
        glTexCoord2f(self.WAVES - self.wave_pos, 1 + self.BACK_WAVE_OFFSET*40)
        glVertex2f(game.width, game.height * (self.back_wave_top + self.BACK_WAVE_OFFSET))
        glTexCoord2f(-self.wave_pos, 1 + self.BACK_WAVE_OFFSET*40)
        glVertex2f(0, game.height * (self.back_wave_top + self.BACK_WAVE_OFFSET))
        glEnd()

        self.trawler.draw_close()
        self.man_back_sprite.draw()
        self.boat_sprite.draw()
        self.man_front_sprite.draw()

        glEnable(self.wave_tex.target)
        glBindTexture(self.wave_tex.target, self.wave_tex.id)
        glTexParameteri(self.wave_tex.target, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(self.wave_tex.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
        glBegin(GL_QUADS)
        glColor3f(*self.FRONT_WAVE_COLOR)
        glTexCoord2f(self.wave_pos, 0)
        glVertex2f(0, self.WAVE_BOTTOM * game.height)
        glTexCoord2f(self.WAVES + self.wave_pos, 0)
        glVertex2f(game.width, self.WAVE_BOTTOM * game.height)
        glTexCoord2f(self.WAVES + self.wave_pos, 1)
        glVertex2f(game.width, self.front_wave_top * game.height)
        glTexCoord2f(self.wave_pos, 1)
        glVertex2f(0, self.front_wave_top * game.height)
        glEnd()

        # Water
        glDisable(self.wave_tex.target)
        glBegin(GL_QUADS)
        glColor3f(*self.WATER_BOTTOM_COLOR)
        glVertex2f(0, 0)
        glVertex2f(game.width, 0)
        glColor3f(*self.WATER_TOP_COLOR)
        glVertex2f(game.width, self.WATER_TOP * game.height)
        glVertex2f(0, self.WATER_TOP * game.height)
        glEnd()

